/* 
 * LRU Cache
 * Design and implement a data structure for Least Recenty Used(LRU) cache.
 * get(key) - Get the value of the key if the key exists in the cache, otherwise return -1.
 * set(key, value) - Set or insert the value is not already presend. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item
 */

#include "../../func.h"

struct CacheNode
{
    int key, ;
    int value;
    CacheNode(int k, int v)
        : key(k), value(v)
    {
    }
};
class LRUCache
{
public:
    LRUCache(int capacity)
    {
        this->capacity = capacity;
    }

    int get(int key)
    {
        if (cacheMap.find(key) == cacheMap.end())
            return -1;
        cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
        cacheMap[key] = cacheList.begin();
        return cacheMap[key]->value;
    }

    void set(int key, int value)
    {
        if (cacheMap.find(key) == cacheMap.end())
        {
            if (cacheList.size() == capacity)
            {
                cacheMap.erase(cacheList.back().key);
                cacheList.pop_back();
            }
            cacheList.push_front(CacheNode(key, value));
            cacheMap[key] = cacheList.begin();
        }
        else
        {
            cacheMap[key]->value = value;
            cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
            cacheMap[key] = cacheList.begin();
        }
    }

private:
    list<CacheNode> cacheList;
    unordered_map<int, list<CacheNode>::iterator> cacheMap;
    int capacity;
};